import pygame
import os
import random
import time
import math
WIDTH=750
HEIGHT=800
FPS=60
FONT_MANE='arial' #is a kind of font(字体）
WHITE=(255,255,255)
BLACK=(0,0,0)
RED=(255,0,0)
GREEN=(0,255,0)
BLUE=(0,0,255)
YELLO=(255,255,0)
LITTLEBLUE=(70,163,142)
LITTLEDARKRED=(221,58,58)
PLAYER_FRICTION_X=-0.055
PLAYER_FRICTION_Y=-0.01
PLAYER_ACC=0.95
CENTER=(WIDTH/2,HEIGHT/2)
LIVES=3
burst_flag=False
burst_begin_time=0
font_name=pygame.font.match_font('arial')#remenber the font_name must be matched not just a name
score=0
pygame.mixer.init()
class Lighting(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.image.load('resource/water.png')
        self.rect=self.image.get_rect()
        self.rect.centerx = random.randrange(0, WIDTH - 100)
        self.rect.centery = random.randrange(-500, 0)
        self.speed_x = 0
        self.speed_y = random.randrange(1, 8)
        lightings.add(self)
    def update(self):
        self.rect.x+=self.speed_x
        self.rect.y+=self.speed_y
        if self.rect.y>HEIGHT:
            self.rect.y=-50
            self.rect.centerx = random.randrange(0, WIDTH - 100)
def draw_texrt(surf,text,size,x,y):
    font=pygame.font.Font(font_name,size)
    text_image=font.render(text,True,WHITE)
    text_rect=text_image.get_rect()
    text_rect.midtop=(x,y)
    surf.blit(text_image,text_rect)
def newmob():
    m=Mob()
    all_sprites.add(m)
    mobs.add(m)
def draw_shild_bar(surf,x,y,pct):
    if pct<0:
        pct=0
    BAR_LENTH=100
    BAR_HEIGHT=10
    fill=(pct/100)*BAR_LENTH
    outline_rect=pygame.Rect(x,y,BAR_LENTH,BAR_HEIGHT)
    fill_rect=pygame.Rect(x,y,fill,BAR_HEIGHT)
    pygame.draw.rect(surf,WHITE,outline_rect,2)
    pygame.draw.rect(surf,GREEN,fill_rect)
def draw_mana_bar():
    MANA_BAR_LENTH=100
    MANA_BAR_HEIGHT=10
    #fill=player.mama/100*MANA_BAR_LENTH
    pygame.draw.rect(screen, WHITE, pygame.rect.Rect(100,80,MANA_BAR_LENTH,MANA_BAR_HEIGHT),2)
    pygame.draw.rect(screen, BLUE, pygame.rect.Rect(100, 80, player.mama/100*MANA_BAR_LENTH, MANA_BAR_HEIGHT))
def move():
    global burst_begin_time
    keys = pygame.key.get_pressed()
    # for event in pygame.event.get():
    # if event.type==pygame.K_DOWN:
    if keys[pygame.K_SPACE]:
        # clock.tick(1)
        if player.mama == 100:
            pygame.mixer.Sound('resource/dingdong.mp3').play()
            player.mama = 0
            burst_begin_time = pygame.time.get_ticks()
            player.shoot_patern += 1
        if pygame.time.get_ticks() - burst_begin_time > 15000:
            player.shoot_patern -= 1
            burst_begin_time=pygame.time.get_ticks()
        if player.shoot_patern >= 3:
            player.shoot_patern = 3
        if player.shoot_patern <= 1:
            player.shoot_patern = 1
        player.shoot()
        shoot_sound = pygame.mixer.Sound('resource/shoot.mp3')
        shoot_sound.set_volume(0.2)
        # shoot_sound.set_volume(0.1)
        shoot_sound.play()
    if keys[pygame.K_LEFT]:
        player.image=pygame.image.load('resource/lingmeng_left.png')
        player.image=pygame.transform.scale(player.image,(60,80))
    elif keys[pygame.K_RIGHT]:
        player.image=pygame.image.load('resource/lingmeng_right.png')
        player.image = pygame.transform.scale(player.image, (60, 80))
    else:
        player.image = pygame.image.load('resource/lingmeng.png')
        player.image = pygame.transform.scale(player.image, (70, 90))
class Shield(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.image.load('resource/shovel.png')
        self.rect=self.image.get_rect()
        self.rect.centerx=random.randrange(0,WIDTH-100)
        self.rect.centery=random.randrange(-10000,-5000)
        self.speed_x=0
        self.speed_y=random.randrange(1,8)
        shields.add(self)
    def update(self):
        self.rect.x+=self.speed_x
        self.rect.y+=self.speed_y
        if self.rect.y>HEIGHT:
            self.rect.y=-50
            self.rect.centerx = random.randrange(0, WIDTH - 100)
class Mob(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image_org=pygame.image.load(random.choice(['resource/pumpkin.png','resource/sunflower_small.png','resource/cabbage.png','resource/ganlan.png','resource/shengcai.png']))
        random_size=random.randrange(50,75)
        self.image_org=pygame.transform.scale(self.image_org,(random_size,random_size))
        self.image=self.image_org.copy()
        #self.image=pygame.transform.scale(self.image,(random.randrange(35,100),random.randrange(35,100)))
        #self.image=pygame.surface.Surface((30,30))
        #self.image.fill((255,0,0))
        self.rect=self.image.get_rect()
        #self.radius=int(self.rect.width /2.2)
        self.radius=30
        #pygame.draw.circle(self.image,RED,self.rect.center,self.radius,0)#the first choice would be self.image ,not self.rect to see the color
        #but no matter if you have color or not pygame.draw.circle is vital for collid judgement
        #the only thing you need to set for self radius is self.radius
        self.rect.x=random.randrange(0,WIDTH-self.rect.width)
        self.rect.y = random.randrange(-320, 0) + 50 * math.log10(score + 1)
        if self.rect.y >= HEIGHT * 0.4:
            self.rect.y = HEIGHT * 0.4
        self.speed_y = random.randrange(1, 7) * (1 + 0.1 * math.log10(score + 1))
        self.speed_x = random.randrange(-7, 7) * (1 + 0.1 * math.log10(score + 1))
        self.last_update = pygame.time.get_ticks()
        self.rot=0
        self.rotate_speed=random.randrange(-8,8)
    def rotate(self):
        self.now=pygame.time.get_ticks()
        if self.now-self.last_update>50:
            self.last_update=self.now
            self.rot=(self.rotate_speed+self.rot)%360
            # the original image will be rote and save it in self.image ,but the image will not stay the same ,so you should not rotate self.image,but you should rotate the origin
            # and after the rotate the center will be changed ,you need to let the center remain to rotate smoothly
            self.old_center=self.rect.center
            self.image=pygame.transform.rotate(self.image_org,self.rot)
            self.rect=self.image.get_rect()#this line is quite vital , that is mainly because the image chang will cause the rect change(the image could be out of rect)
            self.rect.center=self.old_center
            '''self.new_image=pygame.transform.rotate(self.image_org,self.rot)
            self.old_center=self.rect.center
            self.image=self.new_image
            #self.rect=self.image.get_rect()
            self.rect.center=self.old_center'''
    def update(self):
        self.rotate()
        self.rect.y+=self.speed_y
        self.rect.x+=self.speed_x
        if self.rect.top>HEIGHT+10 or self.rect.left>WIDTH or self.rect.right<0:
            self.rect.x = random.randrange(0, WIDTH - self.rect.width)
            self.rect.y = random.randrange(-320, 0) + 50*math.log10(score+1)
            if self.rect.y >= HEIGHT * 0.4:
                self.rect.y = HEIGHT * 0.4
            self.speed_y = random.randrange(1, 7) * (1 + 0.1*math.log10(score+1))
            self.speed_x = random.randrange(-7, 7) * (1 + 0.1*math.log10(score+1))
class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.shoot_patern=1
        self.image = pygame.image.load('resource/lingmeng.png')
        self.image = pygame.transform.scale(self.image, (60,80))
        #self.image.set_colorkey(BLACK)
        #self.image=pygame.surface.Surface((50,40))
        #self.image.fill(GREEN)
        self.rect=self.image.get_rect()
        #self.rect.centerx=WIDTH/2
        #self.rect.centery=HEIGHT/1.2
        self.radius = 7
        pygame.draw.circle(self.image,WHITE, self.rect.center, self.radius)#quite strange:the circle must been drawn before set center
        self.speed_x = 0
        self.speed_y = 0
        self.rect.centerx = WIDTH / 2
        self.rect.centery=HEIGHT/1.2
        self.shild=5
        self.mama=0
        pygame.mixer.music.load('resource/sakura_bgm.mp3')
        pygame.mixer.music.set_volume(2)#the number you need to fill is the times
        pygame.mixer.music.play(loops=-1)
        self.shoot_delay=100
        self.last_shoot=pygame.time.get_ticks()
    def update(self):
        self.speed_y = 0
        self.speed_x = 0
        keys=pygame.key.get_pressed()
        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            self.speed_x=-6
        if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            self.speed_x=6
        if keys[pygame.K_UP] or keys[pygame.K_w]:
            self.speed_y=-6
        if keys[pygame.K_DOWN] or keys[pygame.K_s]:
            self.speed_y=6
        if self.rect.right>=WIDTH:
            self.rect.right=WIDTH
        if self.rect.left<=0:
            self.rect.left=0
        if self.rect.top<=0:
            self.rect.top=0
        if self.rect.bottom>=HEIGHT:
            self.rect.bottom=HEIGHT
        self.rect.x += self.speed_x
        self.rect.y += self.speed_y
    def shoot(self):
        '''if 0<(pygame.time.get_ticks() % 100 )< 40:'''#not sure why division is much more useful than substraction
        if self.shoot_patern==1:
          if pygame.time.get_ticks()-player.last_shoot>player.shoot_delay:
            player.last_shoot=pygame.time.get_ticks()
            bullet=Bullet(self.rect.centerx-30,self.rect.y-80)
            all_sprites.add(bullet)
            bullets.add(bullet)
        '''if 0<(pygame.time.get_ticks() % 100 )< 40:
            bullet=Bullet(self.rect.right-20,self.rect.y-20)
            all_sprites.add(bullet)
            bullets.add(bullet)'''
        if self.shoot_patern==2:
          if pygame.time.get_ticks()-player.last_shoot>player.shoot_delay:
            player.last_shoot=pygame.time.get_ticks()
            bullet=Bullet(self.rect.centerx-70,self.rect.y-80)
            all_sprites.add(bullet)
            bullets.add(bullet)
            bullet = Bullet(self.rect.centerx +10, self.rect.y - 80)
            all_sprites.add(bullet)
            bullets.add(bullet)
        if self.shoot_patern==3:
          if pygame.time.get_ticks()-player.last_shoot>player.shoot_delay:
            player.last_shoot=pygame.time.get_ticks()
            bullet=Bullet(self.rect.centerx-90,self.rect.y-80)
            all_sprites.add(bullet)
            bullets.add(bullet)
            bullet = Bullet(self.rect.centerx +30, self.rect.y - 80)
            all_sprites.add(bullet)
            bullets.add(bullet)
            bullet = Bullet(self.rect.centerx -30, self.rect.y - 80)
            all_sprites.add(bullet)
            bullets.add(bullet)
class Bullet(pygame.sprite.Sprite):
    def __init__(self,x,y):
        pygame.sprite.Sprite.__init__(self)
        #self.image=pygame.surface.Surface((10,10))
        #self.image.fill(YELLO)
        self.image=pygame.image.load('resource/bullet2.png')
        self.image=pygame.transform.scale(self.image,(60,80))
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        self.speed_y=-80
    def update(self):
        self.rect.y+=self.speed_y
        if self.rect.bottom<0:
            self.kill()
class Explosion(pygame.sprite.Sprite):
    def __init__(self,center):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.image.load('resource/bang_picture_1.png')
        self.rect=self.image.get_rect()
        self.rect.center=center
        self.last_time=pygame.time.get_ticks()
    def update(self):
        if 100>pygame.time.get_ticks()-self.last_time>0:
            self.image=pygame.image.load('resource/bang_picture_1.png')
        if 200>pygame.time.get_ticks()-self.last_time>100:
            self.image=pygame.image.load('resource/bang_picture2.png')
        if 300>pygame.time.get_ticks()-self.last_time>200:
            self.image=pygame.image.load('resource/bang_picture3.png')
        if 400>pygame.time.get_ticks()-self.last_time>300:
            self.image=pygame.image.load('resource/bang_picture4..png')
        if pygame.time.get_ticks()-self.last_time>400:
            self.kill()
class Explosion_big(pygame.sprite.Sprite):
    def __init__(self,center):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.image.load('resource/bang_picture_4.png')
        self.image=pygame.transform.scale(self.image,(150,100))
        self.rect=self.image.get_rect()
        self.rect.center=center
        self.last_update=pygame.time.get_ticks()
    def update(self):
        if pygame.time.get_ticks()-self.last_update>1000:
            self.kill()
class Live_icon(pygame.sprite.Sprite):
    def __init__(self,center):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.image.load('resource/lingmeng_small.png')
        self.image=pygame.transform.scale(self.image,(33,40))
        self.rect=self.image.get_rect()
        self.rect.center=center
class ResPlacntIcon(pygame.sprite.Sprite):
    def __init__(self,center):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.image.load(random.choice(['resource/pumpkin.png','resource/sunflower_small.png','resource/cabbage.png','resource/ganlan.png','resource/shengcai.png']))
        self.image=pygame.transform.scale(self.image,(100,120))
        self.rect=self.image.get_rect()
        self.rect.center=center

bakc_ground=pygame.image.load('resource/backGound.png')
bakc_ground=pygame.transform.scale(bakc_ground,(WIDTH,HEIGHT))
bakc_ground_rect=bakc_ground.get_rect()
all_sprites=pygame.sprite.Group()
bullets=pygame.sprite.Group()
mobs=pygame.sprite.Group()
shields=pygame.sprite.Group()
explosions=pygame.sprite.Group()
lightings=pygame.sprite.Group()
mob_list=[pygame.image.load('resource/sunflower_small.png'),pygame.image.load('resource/pumpkin.png'),pygame.image.load('resource/cabbage.png'),pygame.image.load('resource/ganlan.png'),pygame.image.load('resource/shengcai.png')]
for i in range(8):
    mob=Mob()
    pygame.draw.circle(mob.image,RED,mob.rect.center,20)#why this guy is not working
    all_sprites.add(mob)
    mobs.add(mob)
for i in range(1):
    shield=Shield()
    all_sprites.add(shield)
for i in range(5):
    lighting=Lighting()
    all_sprites.add(lighting)
player=Player()
live_icons=pygame.sprite.Group()
live_icon1=Live_icon((WIDTH/2+0+200,HEIGHT/12))
live_icon2=Live_icon((WIDTH/2+40+200,HEIGHT/12))
live_icon3=Live_icon((WIDTH/2+80+200,HEIGHT/12))
live_icons.add(live_icon1)
live_icons.add(live_icon2)
live_icons.add(live_icon3)
all_sprites.add(player)
playing=True
running=True
clock=pygame.time.Clock()
pygame.init()
screen=pygame.display.set_mode((WIDTH,HEIGHT))
screen.fill(WHITE)
pygame.mixer.init()
while running:
    # print(pygame.time.get_ticks())
    clock.tick(FPS)#this guy is very similar to time.sleep
    '''if player.mama == 100:
        player.mana = 0
        burst_time = pygame.time.get_ticks()
        burst_flag = True
        while burst_flag:
            burst_image = pygame.image.load('resource/element_burst.png')
            burst_image = pygame.transform.scale(burst_image, (WIDTH, HEIGHT))
            burst_rect = burst_image.get_rect()
            screen.blit(burst_image, burst_rect)
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
            pygame.display.flip()
            if pygame.time.get_ticks() - burst_time > 1500:
                burst_flag = False'''
    all_sprites.update()
    screen.fill(WHITE)#fill could only be color
    screen.blit(bakc_ground,bakc_ground_rect)
    draw_shild_bar(screen,100,50,100*player.shild/5)
    draw_mana_bar()
    hit_lighting=pygame.sprite.spritecollide(player,lightings,True)
    if hit_lighting:
        score += 50
        lighting=Lighting()
        all_sprites.add(lighting)
        player.mama+=10
        if player.mama>=100:
            player.mama=100
    hit_shield=pygame.sprite.spritecollide(player,shields,True)
    if hit_shield:
        player.shild+=1
        if player.shild>=5:
            player.shild=5
        score+=100
        shield=Shield()
        all_sprites.add(shield)
    hit_player=pygame.sprite.spritecollide(player,mobs,True,pygame.sprite.collide_circle)#you will get a list,and True could kill the group but not the player
    if hit_player:
        m = Mob()
        all_sprites.add(m)
        mobs.add(m)
        explosion_player=Explosion(hit_player[0].rect.center)
        all_sprites.add(explosion_player)
        explosion_player.update()
        hit_player_sound=pygame.mixer.Sound('resource/been_struck.mp3')
        hit_player_sound.set_volume(0.1)
        hit_player_sound.play()
        if hit_player[0].rect.width>50:
              player.shild-=2
        if hit_player[0].rect.width<50:
            player.shild-=1
        if player.shild<=0:
            explosion_death=Explosion_big(player.rect.center)
            explosion_death.image=pygame.transform.scale(explosion_death.image,(85,85))
            all_sprites.add(explosion_death)#this place must be all_sprite that is evey time all_sprite update but the explosions will only update once
            #explosion_death.update()
            player.rect.center=(-500,500)
            player.kill()
            player=Player()
            all_sprites.add(player)
            LIVES-=1
            player.shild=5
            '''if live_icon1:
                live_icon1.kill()
            else:
                if live_icon2:
                    live_icon2.kill()
                else:
                    live_icon3.kill()'''
            for live_icon in live_icons:
                live_icon.kill()
                break
                #live_icon.kill()
            if LIVES<=0:
                death_back_ground=pygame.image.load('resource/backGround2.png')
                death_back_ground=pygame.transform.scale(death_back_ground,(WIDTH,HEIGHT))
                death_back_ground_rect=death_back_ground.get_rect()
                screen.blit(death_back_ground,death_back_ground_rect)
                draw_texrt(screen, f'SCORE:{score}', 50, WIDTH / 2, HEIGHT*0.35)
                draw_texrt(screen,'SPACE TO RESTART',25,WIDTH/2,HEIGHT*0.65)
                draw_texrt(screen,f'Reward:',50,WIDTH/2-50,HEIGHT*0.5)
                res_plant_container=pygame.sprite.Group()
                res_plant=ResPlacntIcon((WIDTH/2+100,HEIGHT*0.5+30))
                res_plant_container.add(res_plant)
                res_plant_container.draw(screen)
                pygame.display.flip()
                stop_flag=True
                while stop_flag:
                    keys=pygame.key.get_pressed()
                    for event in pygame.event.get():
                        if event.type==pygame.QUIT:
                            running=False
                            stop_flag=False
                        if keys[pygame.K_SPACE]:
                            stop_flag=False
                            score=0
                            LIVES=3
                            live_icon1 = Live_icon((WIDTH / 2 + 0 + 200, HEIGHT / 12))
                            live_icon2 = Live_icon((WIDTH / 2 + 40 + 200, HEIGHT / 12))
                            live_icon3 = Live_icon((WIDTH / 2 + 80 + 200, HEIGHT / 12))
                            live_icons.add(live_icon1)
                            live_icons.add(live_icon2)
                            live_icons.add(live_icon3)
            diesound=pygame.mixer.Sound('resource/boom.mp3')
            diesound.set_volume(0.3)
            diesound.play()
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            running=False
    hit_bullet=pygame.sprite.groupcollide(mobs,bullets,True,True)
    if hit_bullet:
     hit_bullet_sound=pygame.mixer.Sound(random.choice(['resource/boom.mp3','resource/boom2.mp3']))
     hit_bullet_sound.set_volume(0.2)
     hit_bullet_sound.play()
     for hit in hit_bullet:
        #for key in hit_bullet:
        explosion=Explosion(hit.rect.center)#this place the hit_bullet is a dict ,and hit is the mobs(actually is a mob being hit)
        all_sprites.add(explosion)#if you put explosion in explosions ,and explosions draw on screeen means you could only draw once
        #if you put the explosion draw into loop the explosion might be not difined
        #so you must draw the sprite
        explosion.update()
        #print(hit)
        #print(hit_bullet)
        score+=20-round(hit.rect.width*0.1)#the hit is actually a list of the sprite in the second group
        m=Mob()
        all_sprites.add(m)
        mobs.add(m)
    for sakura in mobs:
      #if random.randrange(0,100)<50:
         '''if pygame.time.get_ticks()%400<100:
             sakura.image=pygame.image.load('resource/sunflower_small.png')
         if 100<pygame.time.get_ticks()%400<200:
             sakura.image=pygame.image.load('resource/cabbage.png')
         if 200<pygame.time.get_ticks()%400<300:
             sakura.image=pygame.image.load('resource/pumpkin.png')
         if 300<pygame.time.get_ticks()%400<400:
             sakura.image=pygame.image.load('resource/ganlan.png')'''
            #and the coding at top will influence the animation a lot
    move()
    all_sprites.draw(screen)
    draw_texrt(screen, str(score), 50, WIDTH / 2, 30)
    explosions.draw(screen)
    live_icons.draw(screen)
    pygame.display.flip()
pygame.quit()
#236

